package us.gaaoc.framework.dao;

import java.math.BigInteger;
import java.util.Date;
import java.util.List;

import javax.faces.context.FacesContext;

import org.apache.log4j.Logger;
import org.hibernate.FetchMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;

import us.gaaoc.framework.model.Person;

public class PersonDAOHibernate extends GenericHibernateDAO<Person, String, PersonDAO> implements PersonDAO {

	private static final Logger LOG = Logger.getLogger(PersonDAOHibernate.class);
	
	protected PersonDAOHibernate() {}
	
	public Person login(String username, String password) {
		Person person = null;
		
		try {
			// eagerly fetch the Person object
			LOG.debug("SESSION : " + getSession());
			person = (Person) getSession().createCriteria(Person.class)
				.setFetchMode("*", FetchMode.SELECT)
				.add(Restrictions.eq("userId", username))
				.add(Restrictions.eq("password", password))
				.add(Restrictions.eq("deleteUserFlag", (byte)0))
				.uniqueResult();
			LOG.debug("LOGIN : " + person);
			if(person != null){
				Hibernate.initialize(person.getOrganizations());
				Hibernate.initialize(person.getRoles());
				
				if(person.getOrganizations().size() == 1){
					FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("courtUuid", person.getOrganizations().get(0).getCourtUuid());
				}
			}
		} catch (HibernateException e) {
			LOG.error(e);
			throw e;
		}
		return person;
	}
	
	public Person getPersonByUserName(String userName){
		Person person = null;
		try {
			// eagerly fetch the Person object
			person = (Person) getSession().createCriteria(Person.class)
				.setFetchMode("*", FetchMode.SELECT)
				.add(Restrictions.eq("userId", userName))
				.uniqueResult();
			if(person != null){
			//	Hibernate.initialize(person.getProfile());				
			}
		} catch (HibernateException e) {
			LOG.error(e);
			throw e;
		}
		return person;
	}
	
	/*Commented By: Ramu (eppakayr)
	 * public List<Person> getNonDeletedPersonWithNonNullUserId(){		
		LOG.info("Getting the users of the system...");
		Query q = getSession().createQuery("from Person p where p.deleteUserFlag = ? and p.userId != NULL");
		q.setByte(0, (byte) 0);
		return q.list();		
	}*/
	
	public List<Person> getNonDeletedPersonWithNonNullUserId(String courtUuid){		
		LOG.info("Getting the users of the system...");
		Query q = getSession().createQuery("select p from Person p, PersonOrganizations po where p.deleteUserFlag = ? and p.userId != NULL " +
				" and po.courtUuid=:courtUuid and po.person=p");
		q.setByte(0, (byte) 0);
		q.setString("courtUuid", courtUuid);
		return q.list();		
	}
	
	public List<Person> getNonDeletedPerson(){			
		Query q = getSession().createQuery("from Person p where p.deleteUserFlag = ? ");
		q.setByte(0, (byte) 0);
		return q.list();		
	}
	
	public void updatePersonForDeletedFlag(String uuid, byte isDeleted) {
		 //Person person = this.findById(uuid, true);
		Person person = this.findById(uuid);
		 getSession().refresh(person);
		 person.setDeleteUserFlag((byte)1);
		 this.makePersistent(person);
		
	}
	public Person findByPersonName(String first, String middle, String last) {
		Person person = null;
		try {
			// there might be more thatn 1 person with same name, 
			//here we just get the first Person in the list
			// @TODO need to address this problem in future
			List personList =  getSession().createCriteria(Person.class)
				.setFetchMode("*", FetchMode.SELECT)
				.add(Restrictions.eq("firstName", first))
				.add(Restrictions.eq("middleName", middle))
				.add(Restrictions.eq("lastName", last)).list();
			if (personList!=null && !personList.isEmpty()){
				person = (Person)personList.get(0);
			}
		} catch (HibernateException e) {
			LOG.error(e);
			throw e;
		}
		return person;  
		
	}
	public Person findPersonByUuid (String uuid){			
		Query q = getSession().createQuery("from Person p where p.uuid = ?");
		q.setString(0, uuid);
		//return (Person) q.list();		
		return (Person)q.uniqueResult();
		
	}

	/* (non-Javadoc)
	 * @see us.gaaoc.framework.dao.PersonDAO#deletePerson(us.gaaoc.framework.model.Person)
	 */
	public void deletePerson(Person person) {
		String hqlDelete = "delete Person p WHERE p.uuid=?";	

		int deletedEntities = this.getSession().createQuery( hqlDelete )
		        .setString( 0, person.getUuid()).executeUpdate();
		LOG.info("deleted rows "+deletedEntities);
		
		
	}

	@SuppressWarnings("unchecked")
	public List<Person> findPersonListByNameAndByDOB(String firstName, String middleName, String lastName, Date dateOfBirth) {
		
		Query q = getSession().createQuery("from Person p where p.firstName = ? and p.middleName = ? and p.lastName = ? and p.dob = ? ");
		q.setString(0, firstName);
		q.setString(1, middleName);
		q.setString(2, lastName);
		//q.setDate(3, DateUtil.utilToSqlDate(dateOfBirth));
		//q.setDate(3, new java.sql.Timestamp(dateOfBirth.getTime()));
		//q.setDate(3, dateOfBirth);
		q.setDate(3, new java.sql.Date(dateOfBirth.getTime()));
		LOG.debug("The size of the List is "+q.list().size());
		return q.list(); 
	}
	
     //methods added by Bhawana//
	
	//number of Children
	
	public int countChildren() {
		String sql="SELECT COUNT(*) FROM personParticipants WHERE relationshipCode = 1;";
        Query q = getSession().createSQLQuery(sql);
        List l = q.list();
        BigInteger tempResultSize = (BigInteger) l.get(0);
        int resultSetSize = tempResultSize.intValue();
        return resultSetSize;
	}

	public int countDefendents() {
		String sql="SELECT COUNT(*) FROM personParticipants WHERE relationshipCode = 2;";
        Query q = getSession().createSQLQuery(sql);
        List l = q.list();
        BigInteger tempResultSize = (BigInteger) l.get(0);
        int resultSetSize = tempResultSize.intValue();
        return resultSetSize;
	}	
}
